﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCacheDataGetTrans.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-08-14
//    @Email			:    445267987@qq.com
//    @Module           :    NFCacheDataGetTrans
//    @Desc             :    缓存数据获取事务基类实现
//                           提供批量缓存数据获取的统一接口和子事务管理
//                           支持批量/单条查询、插入操作的事务协调
//
// -------------------------------------------------------------------------

#include "NFCacheDataGetTrans.h"

#include "NFCacheDataInsertTrans.h"
#include "NFCacheDataLoadTrans.h"
#include "NFCacheDataSaveTrans.h"

/**
 * @brief 构造函数，根据共享内存模式进行初始化
 * 
 * 根据共享内存管理器的创建模式选择初始化方式：
 * - EN_OBJ_MODE_INIT：冷启动模式，调用 CreateInit() 进行完整初始化
 * - 其他模式：热启动模式，调用 ResumeInit() 进行恢复初始化
 */
NFCacheDataGetTrans::NFCacheDataGetTrans()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

/**
 * @brief 析构函数
 * 
 * 清理资源，由于使用共享内存管理，通常无需特殊处理
 */
NFCacheDataGetTrans::~NFCacheDataGetTrans()
{
}

/**
 * @brief 冷启动创建初始化
 * 
 * 在共享内存冷启动场景下，对所有成员变量进行零值初始化：
 * - m_iServerType：目标存储服务器类型
 * - m_ullRoleId：目标对象ID
 * - m_iTableId：数据表ID/类型标识
 * - m_iReason：调用原因/场景标识
 * 
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::CreateInit()
{
    m_iServerType = 0;
    m_ullRoleId = 0;
    m_iTableId = 0;
    m_iReason = 0;
    return 0;
}

/**
 * @brief 热启动恢复初始化
 * 
 * 在共享内存热启动场景下，从持久化数据恢复对象状态时调用
 * 当前实现为空，如有需要可在此添加恢复逻辑
 * 
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::ResumeInit()
{
    return 0;
}

/**
 * @brief 初始化事务运行参数
 * 
 * 设置事务执行所需的基本参数，通常在创建事务后立即调用
 * 
 * @param serverType 目标存储服务器类型
 * @param roleId      目标对象ID
 * @param tableId     数据表ID，用于标识要操作的数据表
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::Init(int serverType, uint64_t roleId, int tableId)
{
    m_iServerType = serverType;
    m_ullRoleId = roleId;
    m_iTableId = tableId;
    return 0;
}

/**
 * @brief 获取缓存数据批量返回处理（基类默认实现）
 * 
 * 虚函数，子类应重写此方法实现具体的批量查询结果处理逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 * 
 * @param ullId     目标ID
 * @param iTableId  表ID/类型
 * @param iReason   调用原因
 * @param errCode   错误码
 * @param pMessage
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::GetCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode, google::protobuf::Message* pMessage)
{
    LOG_WARN(m_ullRoleId, -1, "GetCacheDataRes not implemented, ullId: {}, iTableId: {}, iReason: {}, errCode: {}", ullId, iTableId, iReason, errCode);
    return 0;
}

/**
 * @brief 获取缓存数据结果处理
 *
 * 该虚函数用于处理缓存数据获取的结果，子类应重写此方法以实现具体的结果处理逻辑。
 *
 * @param ullId     目标对象的唯一标识 ID
 * @param iTableId  数据表 ID/类型标识
 * @param iReason   调用原因/场景标识
 * @param errCode   错误码，表示操作结果
 * @return int 返回处理结果的状态码，通常返回 0 表示成功，非 0 表示失败或错误码
 *
 * @note
 * - 子类需根据业务需求实现该方法，处理查询结果或错误码。
 * - 基类默认实现可能为空或仅输出警告信息。
 * - 确保在子类实现中处理所有可能的错误码和边界情况。
*/
int NFCacheDataGetTrans::OnGetCacheDataFinish(int ullId, int iTableId, int iReason, int32_t errCode)
{
    return 0;
}

/**
 * @brief 插入缓存数据批量返回处理（基类默认实现）
 * 
 * 虚函数，子类应重写此方法实现具体的批量插入结果处理逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 * 
 * @param ullId     目标对象的唯一标识ID
 * @param iTableId  数据表ID/类型
 * @param iReason   调用原因/场景标识
 * @param errCode   错误码，表示操作结果
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::InsertCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode, google::protobuf::Message* pMessage)
{
    LOG_WARN(m_ullRoleId, -1, "InsertCacheDataRes not implemented, ullId: {}, iTableId: {}, iReason: {}, errCode: {}", ullId, iTableId, iReason, errCode);
    SetFinished(0);
    return 0;
}

/**
 * @brief 插入缓存数据完成后的回调处理
 *
 * 该虚函数用于处理缓存数据插入操作完成后的结果，子类应重写此方法以实现具体的结果处理逻辑。
 *
 * @param ullId     目标对象的唯一标识 ID
 * @param iTableId  数据表 ID/类型标识
 * @param iReason   调用原因/场景标识
 * @param errCode   错误码，表示操作结果
 * @return int 返回处理结果的状态码，通常返回 0 表示成功，非 0 表示失败或错误码
 *
 * @note
 * - 子类需根据业务需求实现该方法，处理插入结果或错误码。
 * - 基类默认实现可能为空或仅输出警告信息。
 * - 确保在子类实现中处理所有可能的错误码和边界情况。
 */
int NFCacheDataGetTrans::OnInsertCacheDataFinish(int ullId, int iTableId, int iReason, int32_t errCode)
{
    return 0;
}

/**
 * @brief 保存缓存数据批量返回处理（基类默认实现）
 *
 * 虚函数，子类应重写此方法实现具体的批量保存结果处理逻辑。
 * 基类实现仅输出警告信息，提醒开发者需要在子类中实现。
 *
 * @param ullId     目标对象的唯一标识ID
 * @param iTableId  数据表ID/类型
 * @param iReason   调用原因/场景标识
 * @param errCode   错误码，表示操作结果
 * @return 0 表示成功
 */
int NFCacheDataGetTrans::SaveCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode)
{
    LOG_WARN(m_ullRoleId, -1, "SaveCacheDataRes not implemented, ullId: {}, iTableId: {}, iReason: {}, errCode: {}", ullId, iTableId, iReason, errCode);
    SetFinished(0);
    return 0;
}

/**
 * @brief 发起批量缓存数据查询请求
 * 
 * 创建并初始化子事务来处理批量查询：
 * 1. 更新表ID（如果提供）
 * 2. 创建指定类型的加载事务对象
 * 3. 初始化子事务参数
 * 4. 发起批量查询请求
 * 
 * @param loadTransType 加载事务类型
 * @param vecId         ID列表
 * @param enReason      调用原因/场景标识
 * @param iTableId      数据表ID（可选，为0时使用当前表ID）
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataGetTrans::GetCacheDataBatchReq(int loadTransType, const std::vector<uint64_t>& vecId, int enReason, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataLoadTrans* pTrans = dynamic_cast<NFCacheDataLoadTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(loadTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, className:{} used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetClassName(loadTransType), FindModule<NFIMemMngModule>()->GetUsedCount(loadTransType), FindModule<NFIMemMngModule>()->GetItemCount(loadTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, GetGlobalId());
    int iRetCode = pTrans->LoadCacheDataBatchReq(vecId, enReason);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "LoadCacheDataSingleReq failed, vecId:{}, enReason:{}, transType:{}", NFCommon::tostr(vecId), enReason, loadTransType);
    return 0;
}

/**
 * @brief 发起单条缓存数据查询请求
 * 
 * 创建并初始化子事务来处理单条查询：
 * 1. 更新表ID（如果提供）
 * 2. 创建指定类型的加载事务对象
 * 3. 初始化子事务参数
 * 4. 发起单条查询请求
 * 
 * @param loadTransType 加载事务类型
 * @param ullId         目标ID
 * @param enReason      调用原因/场景标识
 * @param iTableId      数据表ID（可选，为0时使用当前表ID）
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataGetTrans::GetCacheDataSingleReq(int loadTransType, uint64_t ullId, int enReason, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataLoadTrans* pTrans = dynamic_cast<NFCacheDataLoadTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(loadTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(loadTransType), FindModule<NFIMemMngModule>()->GetItemCount(loadTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, GetGlobalId());
    int iRetCode = pTrans->LoadCacheDataSingleReq(ullId, enReason);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "LoadCacheDataSingleReq failed, ullId:{}, enReason:{}, transType:{}", ullId, enReason, loadTransType);
    return 0;
}

/**
 * @brief 单条获取缓存数据请求（带 Protobuf 数据）
 *
 * 创建并初始化子事务来处理单条查询：
 * 1. 更新表 ID（如果提供）
 * 2. 创建指定类型的加载事务对象
 * 3. 初始化子事务参数
 * 4. 发起单条查询请求
 *
 * @param loadTransType 加载事务类型
 * @param ullId         目标对象的唯一标识 ID
 * @param enReason      调用原因/场景标识
 * @param stData        Protobuf 消息对象，包含查询所需的额外信息
 * @param iTableId      数据表 ID（可选，为 0 时使用当前表 ID）
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataGetTrans::GetCacheDataSingleReq(int loadTransType, uint64_t ullId, int enReason, const google::protobuf::Message& stData, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataLoadTrans* pTrans = dynamic_cast<NFCacheDataLoadTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(loadTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(loadTransType), FindModule<NFIMemMngModule>()->GetItemCount(loadTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, GetGlobalId());
    int iRetCode = pTrans->LoadCacheDataSingleReq(ullId, enReason, stData);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "LoadCacheDataSingleReq failed, ullId:{}, enReason:{}, transType:{}", ullId, enReason, loadTransType);
    return 0;
}

/**
 * @brief 发起缓存数据插入请求（带Protobuf消息）
 * 
 * 创建并初始化子事务来处理数据插入：
 * 1. 更新表ID（如果提供）
 * 2. 创建指定类型的插入事务对象
 * 3. 初始化子事务参数
 * 4. 发起插入请求
 * 
 * @param insertTransType 插入事务类型
 * @param ullId           目标ID
 * @param iReason         调用原因
 * @param stPbClass       Protobuf消息对象，包含要插入的数据
 * @param iTableId        数据表ID（可选，为0时使用当前表ID）
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataGetTrans::InsertCacheDataReq(int insertTransType, uint64_t ullId, int iReason, const google::protobuf::Message& stPbClass, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataInsertTrans* pTrans = dynamic_cast<NFCacheDataInsertTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(insertTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(insertTransType), FindModule<NFIMemMngModule>()->GetItemCount(insertTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, GetGlobalId());
    int iRetCode = pTrans->InsertCacheDataReq(ullId, iReason, stPbClass);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "InsertCacheDataReq failed, ullId:{}, enReason:{}, transType:{}", ullId, iReason, insertTransType);
    return 0;
}

/**
 * @brief 发起缓存数据插入请求（不带Protobuf消息）
 * 
 * 创建并初始化子事务来处理数据插入：
 * 1. 更新表ID（如果提供）
 * 2. 创建指定类型的插入事务对象
 * 3. 初始化子事务参数
 * 4. 发起插入请求（子事务内部会构造默认的Protobuf消息）
 * 
 * @param insertTransType 插入事务类型
 * @param ullId           目标ID
 * @param iReason         调用原因
 * @param iTableId        数据表ID（可选，为0时使用当前表ID）
 * @return 0 表示成功，其他值为错误码
 */
int NFCacheDataGetTrans::InsertCacheDataReq(int insertTransType, uint64_t ullId, int iReason, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataInsertTrans* pTrans = dynamic_cast<NFCacheDataInsertTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(insertTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(insertTransType), FindModule<NFIMemMngModule>()->GetItemCount(insertTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, GetGlobalId());
    int iRetCode = pTrans->InsertCacheDataReq(ullId, iReason);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "InsertCacheDataReq failed, ullId:{}, enReason:{}, transType:{}", ullId, iReason, insertTransType);
    return 0;
}

/**
 * @brief 发起缓存数据保存请求
 *
 * 创建并初始化子事务来处理数据保存：
 * 1. 更新表 ID（如果提供）
 * 2. 创建指定类型的保存事务对象
 * 3. 初始化子事务参数
 * 4. 发起保存请求
 *
 * @param saveTransType 保存事务类型
 * @param ullId         目标对象的唯一标识 ID
 * @param iReason       调用原因/场景标识
 * @param stPbClass     Protobuf 消息对象，包含要保存的数据
 * @param iTableId      数据表 ID（可选，为 0 时使用当前表 ID）
 * @return 0 表示成功，其他值为错误码
 *
 * @note 此方法通过事务机制实现数据保存，确保操作的原子性与一致性。
 * @warning 调用前需确保 `stPbClass` 包含完整且正确的保存信息，避免因数据不完整导致的保存失败。
 */
int NFCacheDataGetTrans::SaveCacheDataReq(int saveTransType, uint64_t ullId, int iReason, const google::protobuf::Message& stPbClass, int iTableId)
{
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataSaveTrans* pTrans = dynamic_cast<NFCacheDataSaveTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(saveTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(saveTransType), FindModule<NFIMemMngModule>()->GetItemCount(saveTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, 0, GetGlobalId());
    int iRetCode = pTrans->SaveCacheDataReq(iReason, stPbClass);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "SaveCacheDataReq failed, ullId:{}, enReason:{}, transType:{}", ullId, iReason, saveTransType);
    return 0;
}

/**
 * @brief 发起缓存数据保存请求（带 Protobuf 数据和自定义保存对象）
 *
 * 创建并初始化子事务来处理数据保存：
 * 1. 更新表 ID（如果提供）
 * 2. 创建指定类型的保存事务对象
 * 3. 初始化子事务参数
 * 4. 发起保存请求
 *
 * @param saveTransType 保存事务类型
 * @param ullId         目标对象的唯一标识 ID
 * @param iReason       调用原因/场景标识
 * @param stPbClass     Protobuf 消息对象，包含要保存的数据
 * @param pSaveDb       自定义保存对象，用于扩展保存逻辑
 * @param iTableId      数据表 ID（可选，为 0 时使用当前表 ID）
 * @return 0 表示成功，其他值为错误码
 *
 * @note 此方法通过事务机制实现数据保存，确保操作的原子性与一致性。
 * @warning 调用前需确保 `stPbClass` 和 `pSaveDb` 包含完整且正确的保存信息，避免因数据不完整导致的保存失败。
 */
int NFCacheDataGetTrans::SaveCacheDataReq(int saveTransType, uint64_t ullId, int iReason, const google::protobuf::Message& stPbClass, NFCacheDataWithSaveDb* pSaveDb, int iTableId)
{
    CHECK_NULL(ullId, pSaveDb);
    if (iTableId != 0) { m_iTableId = iTableId; }
    NFCacheDataSaveTrans* pTrans = dynamic_cast<NFCacheDataSaveTrans*>(FindModule<NFIMemMngModule>()->CreateTrans(saveTransType));
    CHECK_NULL_WF(m_ullRoleId, pTrans, "CreateTrans failed, used num:{} all num:{}", FindModule<NFIMemMngModule>()->GetUsedCount(saveTransType), FindModule<NFIMemMngModule>()->GetItemCount(saveTransType));
    pTrans->Init(m_iServerType, m_ullRoleId, m_iTableId, pSaveDb->GetGlobalId(), GetGlobalId());
    int iRetCode = pTrans->SaveCacheDataReq(pSaveDb, iReason, stPbClass);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTrans, "SaveCacheDataReq failed, ullId:{}, enReason:{}, transType:{}", ullId, iReason, saveTransType);
    return 0;
}
